package io.renren.common.aspect;

import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.web.servlet.ShiroHttpServletResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

/**
 * 检测方法执行耗时的spring切面类 使用@Aspect注解的类，Spring将会把它当作一个特殊的Bean（一个切面），也就是不对这个类本身进行动态代理
 * 
 * @author blinkfox
 * @date 2016-07-04
 */
@Aspect
@Component
public class MethodLogAspect {

	private static Log logger = LogFactory.getLog(MethodLogAspect.class);

	// 一分钟，即60000ms
	private static final long ONE_MINUTE = 60000;

	// service层的统计耗时切面，类型必须为final String类型的,注解里要使用的变量只能是静态常量类型的
	public static final String POINT = "execution(* io.renren.modules.*.controller.*.*(..))";
	                                       //execution(* io.renren.common.utils.RedisUtils.*(..))")
	/**
	 * 统计方法执行耗时Around环绕通知
	 * 
	 * @param joinPoint
	 * @return
	 */
	@Around(POINT)
	public Object timeAround(ProceedingJoinPoint joinPoint) {
		// 定义返回对象、得到方法需要的参数
		Object obj = null;
		Object[] args = joinPoint.getArgs();
		long startTime = System.currentTimeMillis();
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
		UUID uuid = UUID.randomUUID();
		this.printTime(methodName, args, startTime, 0,uuid,0);
		try {
			obj = joinPoint.proceed(args);
		} catch (Throwable e) {
			logger.error("统计某方法执行耗时环绕通知出错", e);
		}

		// 获取执行的方法名
		long endTime = System.currentTimeMillis();
		

		// 打印耗时的信息
		this.printTime(methodName, args, startTime, endTime,uuid,1);

		return obj;
	}

	/**
	 * 打印方法执行耗时的信息，如果超过了一定的时间，才打印
	 * 
	 * @param methodName
	 * @param startTime
	 * @param endTime
	 */
	private void printTime(String methodName,Object[] args, long startTime, long endTime,UUID uuid,int flag) {
		if(args.length!=0){
			Object o = args[0];
			if(!(o instanceof ShiroHttpServletResponse)){
				if(flag==0){//开始
					logger.info("-----" + methodName + " 方法执行开始uuid：" + uuid + " 参数为："+JSON.toJSONString(args));
				}else{
					long diffTime = endTime - startTime;
					if (diffTime > ONE_MINUTE) {
						logger.error("-----" + methodName + " 方法执行结束uuid：" + uuid +" 耗时：" + diffTime+" ms");
					}else{
						logger.info("-----" + methodName + " 方法执行结束uuid：" + uuid +" 耗时：" + diffTime+" ms");
					}
				}
			}
		}
	}

}